﻿using System;
using System.ComponentModel;
using System.IO.Ports;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using LDriver;
using LDriver.Protocols;
using LDriver.Providers;


namespace LClient
{
    public partial class frmLidar : XtraForm
    {
        public frmLidar()
        {
            InitializeComponent();

            // Get all the SerialPort
            foreach (string s in SerialPort.GetPortNames())
            {
                cmbPorts.Properties.Items.Add(s);
            }


        }

        // Variabili pubbliche per l'inizializzazione
        public long IDWorkspace = 0;

        private CommunicationManager cm;
        private ICommunicationProtocol prot;
        private ICommunicationProvider prov;

        BackgroundWorker bwMeasurements = new BackgroundWorker();

        // Inizializzazione del CommunicationManager.
        // Vengono impostate le informazioni relative al Provider (USB, RS232, ...)
        // ed al protocollo (Lidar, ...)
        private bool InitializePort()
        {
            if (cmbPorts.SelectedItem==null || cmbPorts.SelectedItem.ToString() == "" || cmbBaudRate.SelectedItem == null) return false;

            prov = new RS232(cmbPorts.SelectedItem.ToString(), Convert.ToInt32(cmbBaudRate.SelectedItem) , Parity.None);

            prot = new LidarProtocol();
            prot.Initialize();

            cm = new CommunicationManager(prov, prot);

            bwMeasurements = new BackgroundWorker();
            bwMeasurements.WorkerSupportsCancellation = true;

            bwMeasurements.DoWork += new DoWorkEventHandler(bwMeasurements_DoWork);
            bwMeasurements.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwMeasurements_RunWorkerCompleted);

            return true;

        }

        // Il comando START
        //private void btnStart_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
            private void button1_Click(object sender, EventArgs e)
        {

            if (InitializePort())
            {

                AppStaticObjects.Logger.Info("Port {0} Status {1}{2}", cmbPorts.SelectedItem.ToString(), prov.IsOpen().ToString(), Environment.NewLine);

                // Imposto le dimensioni del ucVisualizer dedicato al Lidar
                ucVisualizer.Resize(ucVisualizer.Height, ucVisualizer.Width);


                // Invio al CommunicationManager il comando di START presente nel
                // protocollo
                cm.SendCommand(cm.GetCommand("START"));
                txtLog.Text += string.Format("Send Command Start{0}", Environment.NewLine);

                if (bwMeasurements.IsBusy != true) bwMeasurements.RunWorkerAsync();

                btnStart.Enabled = false;
                btnStop.Enabled = true;

            }
            else
            {
                MessageBox.Show("Choose Port and Baud Rate"+ Environment.NewLine);
            }

        }

        // Il comando STOP
        //private void btnStop_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
            private void button2_Click(object sender, EventArgs e)
        {
            // Invio al CommunicationManager il comando di STOP presente nel protocollo
            cm.SendCommand(cm.GetCommand("STOP"));

            if (bwMeasurements.WorkerSupportsCancellation == true) bwMeasurements.CancelAsync();

            btnStart.Enabled = true;
            btnStop.Enabled = false;
        }
        
        private void bwMeasurements_DoWork(object sender, DoWorkEventArgs e)
        {

            while (true)
            {

                // Verifico se è stata richiesta una interruzione delle attività
                if (bwMeasurements.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                    MessageBox.Show("worker.CancellationPending");
                }
                else
                {
                    this.Invoke((MethodInvoker)delegate
                    {
                        // Se ci sono elaborazioni da effettuare
                        if (cm.Measurements.Count > 0)
                        {
                            try
                            {
                                if (cm.Measurements[0] != null) {
                                   // Procedo alla visualizzazione dei dati
                                    
                                    ucVisualizer.DrawPoint(cm.Measurements[0]);
                                }

                                // Eseguita la elaborazione della misurazione la elimino
                                lock (cm.Measurements)
                                {
                                    cm.Measurements.RemoveAt(0);
                                }

                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                            
                        }

                    });

                }

            }

            //MessageBox.Show("???????");

        }

        private void bwMeasurements_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                MessageBox.Show("Canceled!");
            }

            else if (!(e.Error == null))
            {
                MessageBox.Show ("Error: " + e.Error.Message);
            }

            else
            {
                MessageBox.Show("Done!");
            }
        }

        private void frmLidar_Resize(object sender, EventArgs e)
        {

            // Efettuando il resize vado a ridisegnare il contenuto
            // dell'ucVisualizer dedicato al Lidar
            ucVisualizer.Resize(ucVisualizer.Height, ucVisualizer.Width);

        }

        private void btnReset_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            //MessageBox.Show("fake");
        }

        private void cmbPorts_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {

        }

     
    }

}
